const fs = require('fs')
const path = require('path')
const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
const babel = require('@babel/core')
// 获取模板内容
const getModuleInfo = (file) => {
    const body = fs.readFileSync(file, 'utf-8')
    const ast = parser.parse(body, {
        sourceType: 'module' // 要解析的是代码的ES模块
    })
    // console.log(ast.program.body);    
    const deps = {}
    traverse(ast, {  // 遍历AST
        ImportDeclaration({node}) {
            const dirname = path.dirname(file) // 获取到当前文件所处的文件夹的名称
            const abspath = './' + path.join(dirname, node.source.value) // ./src/add.js  拼接
            deps[node.source.value] =abspath  // key: './add.js  value: ./src/add.js
        }
    })
    // console.log(deps);  // 该对象存放了file文件所需的依赖

    const { code } = babel.transformFromAst(ast, null, { // Ast转换代码, 降级处理ES6到ES5
        presets: ['@babel/preset-env']  
    })
    console.log(code); // 得到ES5代码

    const moduleInfo = { file, deps, code} // 路径，依赖，代码
    return moduleInfo
}

const parseModules = (file) => {// 递归获取依赖
    const entry = getModuleInfo(file)
    const temp =[entry]  // [{url, deps, Es5code}]
    for(let i = 0; i < temp.length; i++) {
        const deps = temp[i].deps
        if (deps) {
            for (const key in deps) {  // key == './add.js', value == ./src/add.js
                if (deps.hasOwnProperty(key)) {
                    temp.push(getModuleInfo(deps[key]))
                }
            }
        }
    }
    const depsGraph = {}
    temp.forEach(moduleInfo => {
        depsGraph[moduleInfo.file] = {  // {'./src/index.js' : {deps, code},...}
            deps: moduleInfo.deps,
            code: moduleInfo.code
        }
    })
    console.log(depsGraph);
    return depsGraph
}


const bundle = (file) => {
    const depsGraph = JSON.stringify(parseModules(file))

   return  `(function(graph) {
        function require(file) {
            function absRequire(relPath) {
                return require(graph[file].deps[relPath])
            }
            var exports = {};
            (function(require, exports, code) { // require == absRequire
                eval(code)
            })(absRequire, exports, graph[file].code)
            return exports
        }
        require('${file}')
    })(${depsGraph})`
}
const content = bundle('./src/index.js')    



fs.mkdirSync('./dist') // 入口
fs.writeFileSync('./dist/bundle.js', content)// 出口 写入文件

// require('./src/index.js)
// (function(require, exports, code) { 
//     eval(code)
// })(absRequire, exports, graph[file].code)